<!--
 * @Author: Xujianchen
 * @Date: 2024-07-11 15:03:17
 * @LastEditors: xujianchen
 * @LastEditTime: 2024-07-18 16:26:15
 * @Description: 分段控制器
-->
<template>
  <div
    :class="{
      segmented: true,
      'segmented-block': block,
      'segmented-large': size === 'large',
      'segmented-small': size === 'small',
    }"
  >
    <div class="segmented-group">
      <div
        class="segmented-item-bar"
        :style="{
          width: `${width}px`,
          transform: `translateX(${translateX}px)`,
          display: initStatus ? 'block' : 'none',
          backgroundColor:
            disabled || getDisabledItem() ? getDisabledColor(primaryColor) : '',
        }"
      />
      <template v-for="(item, index) in options" :key="index">
        <div
          :ref="`itemRef${index}`"
          :class="[
            'segmented-item',
            modelValue === index && 'segmented-item-active',
            (disabled || item.disabled) && 'segmented-item-disabled',
          ]"
          @click="handleChange({ item, index })"
        >
          <span
            v-if="item.icon"
            class="segmented-item-icon"
            :style="{ marginRight: item.label ? '4px' : 0 }"
          >
            <icon
              :name="item.icon"
              :type="item.iconType || ICON_TYPE.EL_ICON"
            />
          </span>
          <span class="segmented-item-text" style="line-height: 1">{{
            item.label
          }}</span>
        </div>
      </template>
    </div>
  </div>
</template>

<script setup>
import { useResizeObserver } from '@vueuse/core'
import { ICON_TYPE } from '@/const'
import { getDisabledColor } from '@/app/style'
import useConfigStore from '@/store/modules/config'

const modelValue = defineModel({ type: Number, default: 0 })
const props = defineProps({
  options: {
    type: Array,
    default: () => [],
  },
  /** 是否跟随父元素宽度 */
  block: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  size: {
    type: String,
    default: 'default',
    validator: (value) => ['default', 'large', 'small'].includes(value),
  },
  /** 当内容发生变化时，设置 `resize` 可使其自适应容器位置 */
  resize: {
    type: Boolean,
    default: false,
  },
})
const emit = defineEmits(['change'])

const configStore = useConfigStore()

const primaryColor = computed(() => configStore.globalConfig.primaryColor)

const width = ref(0)
const translateX = ref(0)
const initStatus = ref(false)
const instance = getCurrentInstance()

function handleChange({ item, index }) {
  if (props.disabled || item.disabled) return
  // event.preventDefault()
  modelValue.value = index
  emit('change', { index, item })
}

async function handleInit(index = modelValue.value) {
  await nextTick()
  const curLabelRef = instance?.proxy?.$refs[`itemRef${index}`]
  if (!curLabelRef && !curLabelRef.length) return

  width.value = curLabelRef[0].clientWidth
  translateX.value = curLabelRef[0].offsetLeft
  initStatus.value = true
}

function handleResizeInit() {
  const el = document.querySelector('.segmented')
  useResizeObserver(el, async () => {
    await nextTick()
    handleInit(modelValue.value)
  })
}

function getDisabledItem() {
  return props.options.find(
    (item, index) => index === modelValue.value && item.disabled,
  )
}

;(props.block || props.resize) && handleResizeInit()

watch(
  () => modelValue.value,
  async (newVal) => {
    await nextTick()
    handleInit(newVal)
  },
  { immediate: true },
)

watch(() => props.size, handleResizeInit, { immediate: true })
</script>

<style scoped lang="scss">
@import './index.scss';
</style>
